#include"jpg.h"

struct jpeg_info *jpg2rgb(const char *filename){
    static struct jpeg_info jinfo;
    //获取jpg文件名
    jinfo.filename = filename;

    //获取jpg文件大小
    struct stat st;
    bzero(&st, sizeof(st));//不熟练
    stat(filename, &st);
    jinfo.jpg_size = st.st_size;

    //打开jpg图片
    FILE *fp = fopen(filename, "r");
    if(!fp){
        printf("打开%s失败:%s\n", filename, strerror(errno));
        return NULL;
    }
    //读jpg图片信息
    //对fread函数不熟悉，忘记了返回值是成功读取数据块的大小、参数类型
    jinfo.jpg_data = malloc(jinfo.jpg_size);
    int n = fread(jinfo.jpg_data, jinfo.jpg_size, 1, fp);
    if(n < 1){
        perror("读文件失败");
        return NULL;
    }


    //新知识：主要难点、记忆点
    struct jpeg_decompress_struct cinfo;// 解压缩核心结构体
    struct jpeg_error_mgr jerr;// 错误管理结构体

    cinfo.err = jpeg_std_error(&jerr);//将错误管理结构体jerr与解压缩结构体dcp_info关联
    jpeg_create_decompress(&cinfo);//初始化解压缩结构体

    //配置解压缩结构体，使其从jpg_data中读取jpg_size个字节
    jpeg_mem_src(&cinfo, jinfo.jpg_data, jinfo.jpg_size);

    //读jpeg格式头, 判断其格式是否合法
    if(!jpeg_read_header(&cinfo, true)){//true表示要求 libjpeg 严格验证 JPEG 格式
        perror("jpeg_read_header failed!");
        return NULL;
    }

    //开始解码
    jpeg_start_decompress(&cinfo);

    //保存并显示图片的尺寸信息
    printf("图片规格:%d × %d\n", jinfo.width = cinfo.output_width, jinfo.height = cinfo.output_height);
    printf("色深:%d\n", 8 * (jinfo.components = cinfo.output_components));

    //根据图片大小分配一块放rgb_data的内存,大小需根据解码数据计算
    jinfo.rgb_size = jinfo.width * jinfo.components * jinfo.height;
    jinfo.rgb_data = calloc(1, jinfo.rgb_size);

    //循环地将解码出地每一行数据放入rgb_data地每一行中
    while(cinfo.output_scanline < jinfo.height){
        unsigned char *buffer_array[1];
        buffer_array[0] = jinfo.rgb_data + cinfo.output_scanline * jinfo.width * jinfo.components;
        jpeg_read_scanlines(&cinfo, buffer_array, 1);
    }

    //释放相关资源
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(fp);
    return &jinfo;
}